package com.agentfactory.teleoreactive.compiler;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.agentfactory.logic.update.lang.AND;
import com.agentfactory.logic.update.lang.IFormula;
import com.agentfactory.logic.update.lang.IMPLIES;
import com.agentfactory.logic.update.lang.ITerm;
import com.agentfactory.logic.update.lang.Predicate;
import com.agentfactory.teleoreactive.interpreter.Utilities;
import com.agentfactory.teleoreactive.interpreter.mentalstate.TRProgram;
import com.agentfactory.teleoreactive.interpreter.mentalstate.TRRule;

public class CodeGeneratorVisitor implements TeleoReactiveParserVisitor {
	public Map<Predicate, String> actions = new HashMap<Predicate, String>();
	public Map<Predicate, String> sensors = new HashMap<Predicate, String>();
	public List<Predicate> beliefs = new LinkedList<Predicate>();
	public List<IMPLIES> resolutionRules = new LinkedList<IMPLIES>();
	public Map<String, TRProgram> programs = new HashMap<String, TRProgram>();
	@Override
	public Object visit(SimpleNode node, Object data) {
		PredicateConstructorVisitor visitor = new PredicateConstructorVisitor();
		if (node.toString().equals("SensorExpression")) {
			String predicate = (String) visitor.visit((SimpleNode) node.jjtGetChild(0), null);
			String cname = (String) ((SimpleNode) node.jjtGetChild(1)).jjtGetValue();
			if (cname != null) {
				sensors.put((Predicate) Utilities.factory.createFormula(predicate), cname);
			}
		} else if (node.toString().equals("ActionExpression")) {
			String predicate = (String) visitor.visit((SimpleNode) node.jjtGetChild(0), null);
			String cname = (String) ((SimpleNode) node.jjtGetChild(1)).jjtGetValue();
			if (cname != null) {
				actions.put((Predicate) Utilities.factory.createFormula(predicate), cname);
			}
		} else if (node.toString().equals("FuncExpression")) {
			
			List<TRRule> rules = new LinkedList<TRRule>();
			List<ITerm> arguments = new LinkedList<ITerm>();
			SimpleNode function = (SimpleNode) node.jjtGetChild(0);
			Predicate functiondec = (Predicate) Utilities.factory.createFormula((String) visitor.visit(function, null));
			for (int i = 0; i < functiondec.size(); i++) {
				arguments.add(functiondec.termAt(i));   
            }
			String funName = Utilities.createSignature(functiondec);
			// get name of function
			for (int i = 1; i < node.jjtGetNumChildren(); i++) {// for each rule load and add to trprog
				TRRule r = (TRRule)visit(((SimpleNode)node.jjtGetChild(i)), data);
				rules.add(r);
			}
			TRProgram prog = new TRProgram(funName, rules, arguments);
			programs.put(funName, prog);
		} else if (node.toString().equals("ResolutioRuleExp")) {
			String rule = (String) node.jjtGetValue();
//			String Cond = (String) Utilities.presenter.toString((IFormula)new SentenceBuilderVisitor().visit((SimpleNode)node.jjtGetChild(0), null));
//			String Implies = (String) visitor.visit((SimpleNode)node.jjtGetChild(1), null);
			IFormula i = Utilities.factory.createFormula(rule.substring(1, rule.length()-1));
			if(IMPLIES.class.isInstance(i)){
				resolutionRules.add((IMPLIES)i);
			}
			
		} else if (node.toString().equals("Predicate")) {
			String predicate = (String) visitor.visit(node, null);
			beliefs.add((Predicate) Utilities.factory.createFormula(predicate));
		} else if(node.toString().equals("RuleExpression")){
			AND and = (AND) new SentenceBuilderVisitor().visit((SimpleNode) node.jjtGetChild(0), null);
			String predicateAction = (String) visitor.visit((SimpleNode) node.jjtGetChild(1), null);
			IFormula act = Utilities.factory.createFormula(predicateAction);
			TRRule rule = new TRRule(and, act);
			return rule;
			
		}else if (node.toString().equals("IncludeExpression")) {
			// IGNORE: This should never be called
		} else {
			for (int i=0; i<node.jjtGetNumChildren(); i++) {
				visit((SimpleNode) node.jjtGetChild(i), data);
			}
		}
		return null;
	}

}
